package org.example.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.apache.shardingsphere.shardingjdbc.jdbc.core.datasource.ShardingDataSource;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.configuration.FluentConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.DatabaseMetaData;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Configuration
//@EnableTransactionManagement
public class SpTableShardingJdbcConfigure {

    @Lazy
    @Resource
    private ShardingDataSource shardingDataSource;

    @Primary
    @Bean
    public MultiModuleFlywayMigrationStrategy initFlyway(){
        Map<String, DataSource> dataSourceMap = shardingDataSource.getDataSourceMap();
        List<FluentConfiguration> migrations = new ArrayList<>(dataSourceMap.size());
        dataSourceMap.forEach((dsName, ds)->{
            FluentConfiguration configuration = Flyway.configure()
                    .dataSource(ds)
                    .locations("classpath:sql/"+getDbType(ds).name().toLowerCase())
                    .table("pm_flyway_schema")
                    .baselineOnMigrate(true)
                    .baselineVersion("0")
                    .validateOnMigrate(false)
                    ;
            migrations.add(configuration);
        });
        return new MultiModuleFlywayMigrationStrategy(migrations);
    }

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(DataSource dataSource) {
        DbType dbType = getDbType(dataSource);
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
        paginationInnerInterceptor.setOptimizeJoin(true);
        paginationInnerInterceptor.setDbType(dbType);
        paginationInnerInterceptor.setOverflow(true);
        interceptor.addInnerInterceptor(paginationInnerInterceptor);
        OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor = new OptimisticLockerInnerInterceptor();
        interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor);
        return interceptor;
    }

    private static DbType getDbType(DataSource dataSource){
        String databaseProductName = null;
        try {
            DatabaseMetaData databaseMetaData = dataSource.getConnection().getMetaData();
            databaseProductName = databaseMetaData.getDatabaseProductName();
        }catch (Exception e){
            e.printStackTrace();
        }
        if("oracle".equalsIgnoreCase(databaseProductName)){
            return DbType.ORACLE;
        }
        return DbType.MYSQL;
    }

//    @Bean
    public PlatformTransactionManager txManager() {
        return new DataSourceTransactionManager(shardingDataSource);
    }

    @Bean
    public JdbcTemplate jdbcTemplate(){
        return new JdbcTemplate(shardingDataSource);
    }

    @Bean
    public NamedParameterJdbcTemplate namedParameterJdbcTemplate(){
        return new NamedParameterJdbcTemplate(shardingDataSource);
    }

}
